﻿#ifndef _TCPCLIENT_H_
#define _TCPCLIENT_H_

#include "CELL.h"
#include "MessageHeader.hpp"
#include "CELLNetWork.hpp"
#include "CELLClient.hpp"
#include <stdio.h>
#include <string.h>

class EasyTcpClient
{
protected:
	CELLClient* _pClient = nullptr;

	bool _isConnected = false;

	// 在epoll中用于创建epoll根节点
	virtual void OnInitSocket() {}

	// 在epoll中用于挂载节点
	virtual void OnConnect() {}
public:
	// 构造
	EasyTcpClient();

	// 虚析构
	virtual ~EasyTcpClient()
	{
		Close();
	}

	// 初始化
	int initSocket(int sendSize = SEND_BUF_SIZE, int recvSize = RECV_BUF_SIZE)
	{
		CELLNetWork::Init();
		if (_pClient != nullptr)
		{// 如果已经初始化，先释放
			CELLLog_Warning("close old connect _sock : %d", (int)_pClient->sockfd());
			Close();
		}

		SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
		if (sock == SOCKET_ERROR)
		{
			CELLLog_Error("create _sock error");
			return -1;
		}
		else
		{
			// CELLLog_Info("create _sock : %d succssful", (int)sock);
			_pClient = new CELLClient(sock, sendSize, recvSize);
			OnInitSocket();
			return sock;
		}
	}

	// 连接
	int Connect(const char *ip, unsigned short port)
	{
		if (_pClient == nullptr)
		{
			if (initSocket() == SOCKET_ERROR)
			{
				return SOCKET_ERROR;
			}
		}

		struct sockaddr_in serv_addr;
		serv_addr.sin_family = AF_INET;
		serv_addr.sin_port = htons(port);
		serv_addr.sin_addr.s_addr = inet_addr(ip);
		int ret = connect(_pClient->sockfd(), (struct sockaddr*) & serv_addr, sizeof(serv_addr));
		if (ret == SOCKET_ERROR)
		{
			CELLLog_Error("<socket=%d>connect  error", (int)_pClient->sockfd());
		}
		else
		{
			_isConnected = true;
			OnConnect();
			// CELLLog_Info("connect to %s:%u successful", ip, port);
		}
		return ret;
	}

	// 关闭
	virtual void Close()
	{
		if (_pClient != nullptr)
		{
			delete _pClient;
			_pClient = nullptr;
			_isConnected = false;
		}
	}
	
	// 发送数据
	// 处理网络消息
	virtual bool OnRun(int microseconds = 1) = 0;

	// 是否工作中
	inline bool IsRun()
	{
		return _isConnected;
	}

	// 接收数据 处理 粘包 拆包
	int RecvData()
	{
		if (IsRun())
		{
			int nLen = _pClient->RecvData();
			if (nLen > 0)
			{
				DoMsg();
			}
			return nLen;
		}
		return 0;
	}

	void DoMsg()
	{
		while (_pClient->hasMsg())
		{
			OnNetMsg(_pClient->front_msg());
			_pClient->pop_front_msg();
		}
	}

	// 处理消息 返回响应(由继承的子类实现)
	virtual void OnNetMsg(DataHeader* header) = 0;

	// 发送数据
	int SendData(DataHeader* header)
	{
		if (IsRun())
			return _pClient->SendData(header);
		return 0;
	}

	int SendData(const char* pData, int nLen)
	{
		if (IsRun())
			return _pClient->SendData(pData, nLen);
		return 0;
	}
};

#endif // #ifndef _TCPCLIENT_H_